package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.StrategySearchRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {

    @Autowired
    private StrategySearchRepository repository;


    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    public List<Map<String, Object>> queryThemeCommends() {
        //需求要求:
        //1:需要排行, 按照攻略个数排行
        //2:取前面10个
        //3:去除重复目的地
        List<Map<String, Object>> data = new ArrayList<>();
        List<StatisVO> themes = this.statisGroup("themeId", "themeName", "themeGroup", null);
        //======取前面10个========================
        if (themes.size() > 10){
            themes = themes.subList(0, 10); //SubList();
        }
        //#########遍历List<StatisVO> 得到每个主题关联目的地集合#####################
        Map<String, Object> map = null;
        for (StatisVO theme : themes) {
            map = new HashMap<>();
            //左边为主题对象
            map.put("theme", theme);
            //目的地集合
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());
            //右边主题关联目的地集合
            map.put("dests", dests);
            data.add(map);
        }
        return data;
    }

    // 通过主题id查询目的地的id name
    private List<StatisVO> getDestByThemeId(Long themeId) {

        //===3:去除重复目的地========================
        //jpa 的语法规范: findBy属性名
        List<StrategyTemplate>  list = repository.findByThemeId(themeId);

        List<StatisVO> dests = new ArrayList<>();
        //已经存在目的地名
        List<String> names = new ArrayList<>();
        for (StrategyTemplate template : list) {
            if(!names.contains(template.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(template.getDestId());
                vo.setName(template.getDestName());
                dests.add(vo);
                names.add(template.getDestName());
            }
        }
        return dests;
    }

    public List<StatisVO> statisGroup(String idFeild, String nameFeild, String groupName, BoolQueryBuilder query){
        //#########执行es DSL分组查询语句得到List<StatisVO>   id name count#####################
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new  TermsValuesSourceBuilder("id");
        idSource.field(idFeild);
        TermsValuesSourceBuilder nameSource = new  TermsValuesSourceBuilder("name");
        nameSource.field(nameFeild);
        sources.add(idSource);
        sources.add(nameSource);
        //分组集合对象:参数1: 分组查询名称, 参数2:分组列的集合: themeId themeName
        CompositeAggregationBuilder aggrBuilder = new  CompositeAggregationBuilder(groupName, sources);
        //DSL 拼接对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggrBuilder);
        builder.withPageable(PageRequest.of(0, 1));

        //过滤条件
        //BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(query != null){
            builder.withQuery(query);
        }
        //执行DSL语句, 并且解析结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        CompositeAggregation themeGroup = page.getAggregations().get(groupName);
        List<? extends CompositeAggregation.Bucket> buckets = themeGroup.getBuckets();
        List<StatisVO> themes = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : buckets) {
            Long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name  = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();
            themes.add(new StatisVO(id, name, count));
        }

        //====需要排行, 按照攻略个数排行=====
        Collections.sort(themes, new Comparator<StatisVO>() {
            //22对象比较, 根据返回值决定在list集合顺序
            //返回 大于 0 : 大于
            //返回 小于 0 : 小于
            //返回 等于 0 : 等于
            public int compare(StatisVO o1, StatisVO o2) {
                //Long ret = o1.getCount() - o2.getCount(); //正序
                Long ret = o2.getCount() - o1.getCount();  //倒序
                return ret.intValue();
            }
        });
        return themes;
    }

    public List<StatisVO> queryConditionThemes() {
        return this.statisGroup("themeId", "themeName", "themeGroup", null);
    }

    public List<StatisVO> queryConditionProvinces() {
        return this.statisGroup("provinceId", "provinceName", "provinceGroup", null);
    }

    public List<StatisVO> queryConditionCountries() {
        //排除中国
        BoolQueryBuilder query = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));
        return this.statisGroup("countryId", "countryName", "countryGroup",query);
    }

    public Page query(SearchQueryObject qo) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD){
            //国外  : countriyId = qo.getTypeValue()
            builder.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_CHINA){
            //国内
            builder.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME){
            //主题
            builder.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
        }
        return repository.search(builder, qo.getPageable());
    }

    @Override
    public List<StrategyTemplate> findByDestName(String name) {
        return repository.findByDestName(name);
    }

}
